<template>
  <div class="home">
    <div v-show="showNameList" class="name-list">
      <el-button type="primary" style="margin-left: 5%" size="small" @click="createNewTemplate">
        新建话术模板
      </el-button>
      <el-button v-show="curSelectTemplate.id !== -1" type="primary" style="margin-left: 20%" size="small" @click="enterIntentionCenter">
         意向设置
      </el-button>
      <el-table
        :data="templateNameList"
        ref="templateNameList"
        style="width: 250px"
        highlight-current-row
        @row-click="handleRowClick"
      >
        <!--        <el-table-column prop="name" label="话术模板列表" width="180" style="font-c: #20a0ff"/>-->
        <el-table-column prop="name" class="custom-color" label="话术模板列表:" width="250px" />
      </el-table>
    </div>
    <!-- 左侧模块菜单 -->
    <div v-show="showMenuBar" class="menu-bar">
      <!--      <el-button type="primary" @click="save">保存</el-button>-->
      <h2>话术类型</h2>
      <!-- 模块列表 -->
      <div class="menu-list">
        <div
          v-for="item in moduleList"
          :key="item.id"
          draggable="true"
          @dragend="handleDragEnd($event, item)"
          @mousedown="startDragToGraph(item, $event)"
        >
          <p>{{ item.name }}</p>
        </div>
      </div>
    </div>
    <!-- 意向中心-->
    <div v-show="showIntentionCenter" class="intention-center">
      <div class="top">
        <el-button type="primary" style="margin-right: 150px" size="small" @click="exitIntentionCenter">
          返回流程绘制
        </el-button>
        <span>意向中心</span>
      </div>
      <div class="middle">
        <el-button type="primary" size="small" style="margin-right: 150px" @click="addIntention">添加意向</el-button>
        <span>意向类型：</span>
        <el-radio-group @change="intentionTypeChange" v-model="intentionType">
          <el-radio label="0" size="small">单意向</el-radio>
          <el-radio label="1" size="small">多意向</el-radio>
        </el-radio-group>
      </div>
      <div class="content">
        <el-table style="width: 100%" :data="intentionData">
          <el-table-column prop="sort" label="优先级" />
          <el-table-column prop="category" label="分类" />
          <el-table-column prop="name" label="名称" />
          <el-table-column prop="remark" label="备注" />
          <el-table-column prop="address" label="操作">
            <template v-slot="scope">
              <el-button
                type="warning"
                size="mini"
                style="margin-left: 12px;margin-bottom: 2px"
                @click="updateIntention(scope.row)"
              >
                修改
              </el-button>
              <el-button
                type="danger"
                size="mini"
                @click="deleteIntention(scope.row)"
              >
                删除
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>
    <!-- 画布部分 -->
    <div class="canvas-card">
      <div id="container" @dragover="dragoverDiv"></div>
    </div>

    <!--    弹出框-->
    <!--创建新话术弹出框-->
    <el-dialog
      title="节点属性"
      v-model="dialogFormVisible"
      :before-close="onNodeCancel"
    >
      <el-form
        ref="nodeForm"
        :rules="nodeRules"
        :model="nodeForm"
        label-width="140px"
      >
        <el-form-item
          label="模板名称"
          v-if="newNodeInfo.name === '开场白'"
          prop="name"
        >
          <el-input v-model="nodeForm.name" />
        </el-form-item>

        <el-form-item label="话术类型" prop="type">
          <el-select
            v-model="nodeForm.type"
            :placeholder="newNodeInfo.name"
            disabled
          ></el-select>
        </el-form-item>

        <el-form-item label="分类场景">
          <el-select
            filterable
            v-model="nodeForm.category"
            placeholder="请选择分类"
            @change="getScene(nodeForm.category)"
          >
            <el-option
              v-for="(item, i) in categoryList"
              :label="item"
              :value="item"
              :key="i"
            ></el-option>
          </el-select>
          <el-select
            filterable
            v-model="nodeForm.scene"
            placeholder="请选择场景"
          >
            <el-option
              v-for="(item, i) in sceneList"
              :label="item.value"
              :value="item.value"
              :key="i"
            ></el-option>
          </el-select>
        </el-form-item>

        <el-form-item label="话术语音" prop="language">
          <el-radio-group v-model="nodeForm.language">
            <el-radio label="全合成" />
            <el-radio label="全录音" />
          </el-radio-group>
        </el-form-item>

        <el-form-item v-if="nodeForm.language === '全合成'" label="录音员" prop="recorder">
          <el-select v-if="nodeForm.language === '全合成'" v-model="nodeForm.recorder" placeholder="请选择录音员">
            <el-option
              v-for="(item, i) in recorderList"
              :label="item.name"
              :value="item.name"
              :key="i"
            ></el-option>
          </el-select>
          <el-button type="primary" style="margin-left:10px;margin-right: 10px" @click="startPlayOrPause">
            {{ audioButton }}
          </el-button>
        </el-form-item>

        <el-form-item v-if="nodeForm.language === '全录音'" label=" " prop="audioPath">
          <el-button type="primary" style="margin-left:10px;margin-right: 10px" @click="startPlayOrPause">
            {{ audioButton }}
          </el-button>
          <el-upload
            class="upload-audio"
            action=""
            :http-request="uploadAudio"
            :on-success="uploadAudioSuccess"
            :show-file-list="false"
            :accept="'.wav'"
          >
            <el-button prop="audioPath" v-if="nodeForm.language === '全录音'" type="primary">上传音频</el-button>
          </el-upload>
        </el-form-item>

        <el-form-item
          label="语速"
          style="display: flex; flex-direction: row; align-items: center"
        >
          <el-slider
            v-model="speedValue50"
            :format-tooltip="formatTooltip"
            style="width: 75%;margin-right: 10px"
            :min="12.5"
          ></el-slider>
          <el-input-number
            v-model="audio.speed"
            @change="handleChangeSpeed"
            :min="0.25"
            :max="2"
            label=""
            :step="0.25"
          ></el-input-number>
        </el-form-item>

        <el-form-item>
          <audio ref="audio" :src="audioUrl"></audio>
        </el-form-item>

        <el-form-item label="参数标准">
          <el-transfer
            v-model="variablesArr"
            filterable
            :filter-method="filterMethod"
            filter-placeholder="输入参数名搜索"
            :titles="['可选参数', '已选参数']"
            :data="variables"
            @change="variableChange"
          ></el-transfer>
        </el-form-item>

        <el-form-item label="话术内容" prop="content">
          <el-input
            v-model="nodeForm.content"
            :autosize="{ minRows: 4, maxRows: 8 }"
            type="textarea"
            placeholder="请输入内容"
          />
        </el-form-item>

        <!--        高级配置-->
        <el-collapse style="margin-left: 65px;margin-bottom: 20px" v-model="isShowHighConfig">
          <el-collapse-item title="高级配置">
            <el-form-item
              label="通话开始停顿时长"
              style="display: flex; flex-direction: row; align-items: center;"
            >
              <el-slider
                style="width:85%"
                v-model="highConfig.beginTime"
                :format-tooltip="formatBeginTime"
              ></el-slider>
              <span style="margin-left: 10px;margin-right: 15px">
            {{ highConfig.beginTime / 20 }}秒
          </span>
              <el-tooltip
                class="item"
                effect="light"
                content="通话开始时,停顿设置的时间后,AI开始说话"
                placement="right"
              >
                <i class="el-icon-question"></i>
              </el-tooltip>
            </el-form-item>
            <el-form-item
              label="挂机等待时长"
              style="display: flex; flex-direction: row; align-items: center;"
            >
              <el-slider
                v-model="highConfig.waitTime"
                style="width:85%"
                :format-tooltip="formatWaitTime"
              ></el-slider>
              <span style="margin-left: 10px;margin-right: 15px">
            {{ highConfig.waitTime / 20 }}秒
          </span>
              <el-tooltip
                class="item"
                effect="light"
                content="AI发起挂机后等待设定的时间后才挂断电话"
                placement="right"
              >
                <i class="el-icon-question"></i>
              </el-tooltip>
            </el-form-item>
            <el-form-item
              label="用户不回复等待时长"
              style="display: flex; flex-direction: row; align-items: center;"
            >
              <el-slider
                v-model="highConfig.noResponseTime"
                style="width:85%"
                :format-tooltip="formatNoResponseTime"
              ></el-slider>
              <span style="margin-left: 10px;margin-right: 15px">
            {{ highConfig.noResponseTime / 10 }}秒
          </span>
              <el-tooltip
                class="item"
                effect="light"
                content="通话过程中,如用户不回复,等待设定的时间后触发"
                placement="right"
              >
                <i class="el-icon-question"></i>
              </el-tooltip>
            </el-form-item>
            <el-form-item label="降噪等级">
              <el-select v-model="nodeForm.jzdj" placeholder="请选择">
                <el-option
                  v-for="(item, i) in jzdjList"
                  :label="item"
                  :value="item"
                  :key="i"
                ></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="识别模式">
              <el-select v-model="nodeForm.sbms" placeholder="请选择">
                <el-option
                  v-for="(item, i) in sbmsList"
                  :label="item"
                  :value="item"
                  :key="i"
                ></el-option>
              </el-select>
            </el-form-item>
          </el-collapse-item>
        </el-collapse>

        <el-form-item>
          <el-button type="primary" @click="onNodeSubmit">确认</el-button>
          <el-button @click="onNodeCancel">取消</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>

    <!--    跳转类型弹出层-->
    <el-dialog
      title="跳转类型"
      v-model="answerTypeDialogVisible"
      :before-close="onNodeCancel"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :show-close="false"
    >
      <el-form ref="edgeFormRef" :model="edgeForm" :rules="edgeRules">
        <el-form-item prop="answerType">
          <el-select
            v-model="edgeForm.answerType"
            multiple
            placeholder="请选择话术跳转类型"
          >
            <el-option
              v-for="type in unSelectedAnswerTypes"
              :key="type"
              :label="type"
              :value="type"
            />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="onEdgeLabelSubmit">确认</el-button>
          <el-button @click="onEdgeLabelCancel">取消</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>

    <!--    添加意向弹出层-->
    <el-dialog
      :title="intentionDialogTitle"
      v-model="intentionDialogFormVisible"
      :before-close="intentionDialogHandleClose"
    >
      <el-form v-model="intentionForm">
        <el-form-item label="分类">
          <el-radio-group  v-model="intentionForm.category">
            <el-radio label="A">A类</el-radio>
            <el-radio label="B">B类</el-radio>
            <el-radio label="C">C类</el-radio>
            <el-radio label="D">D类</el-radio>
            <el-radio label="E">E类</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="名称">
          <el-input
            v-model="intentionForm.name"
            placeholder="最多输入20个字符"
            />
        </el-form-item>

        <el-form-item label="备注">
          <el-input
            v-model="intentionForm.remark"
            :autosize="{ minRows: 4, maxRows: 8 }"
            type="textarea"
            placeholder="最多输入100个字符（非必填）"
          />
        </el-form-item>

        <el-form-item label="优先级" v-show="intentionType === '0'">
          <el-input-number v-model="intentionForm.sort" :min="1"  :max="this.intentionMaxSort"/>
        </el-form-item>

        <el-form-item label="判断规则">
          <div>
            <div style="margin-bottom: 10px">满足下列[所有]条件</div>
            <div style="margin-bottom: 10px">
              <el-select
                v-model="intentionForm.allCondition"
                multiple
                placeholder="请选择条件"
              >
                <el-option
                  v-for="type in intentionJudgeConditionList"
                  :key="type"
                  :label="type"
                  :value="type"
                />
              </el-select>
            </div>
            <div style="margin-bottom: 10px">满足下列[任意]条件</div>
            <div style="margin-bottom: 10px">
              <el-select
                v-model="intentionForm.anyCondition"
                multiple
                placeholder="请选择条件"
              >
                <el-option
                  v-for="type in intentionJudgeConditionList"
                  :key="type"
                  :label="type"
                  :value="type"
                />
              </el-select>
            </div>
          </div>
        </el-form-item>

        <el-form-item>
          <el-button type="primary" @click="intentionHandle">确认</el-button>
          <el-button @click="intentionDialogHandleClose">取消</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>
  </div>
</template>

<script>
import { Graph } from '@antv/x6'
import { DagreLayout } from '@antv/layout'
import Tools from '@/assets/js/graphTools.js'
import {
  getCategory,
  getParamData, getRecorderList,
  getScene,
  getSimpleList,
  getTemplateFlowDiagram,
  getTemplateNameList
} from "@/api/talkTemplateBase/param";
import axios from 'axios'
import {
  addTemplateEdge,
  deleteTemplateAll, deleteTemplateById,
  deleteTemplateEdge,
  deleteTemplateNode,
  getTemplateById,
  updateTemplateInFlowDiagram
} from "@/api/talkTemplateBase/talkTemplate";
import { addIntention, deleteIntentionById, getIntentionData, updateIntention } from "@/api/talkTemplateBase/intention";
import { Addon } from '@antv/x6'
import request from "@/utils/request";
export default {
  data() {
    return {
      graph: null, // 画布实例对象
      // graphData: {
      //   nodes: [],
      //   edges: []
      // },
      curSelectNode: null, // 当前选中的节点
      // 节点集合
      moduleList: [
        {
          id: 1,
          name: '开场白',
          type: 'initial', // 初始模块(用于区分样式)
        },
      ], // 列表可拖动模块
      // 话术模板名称集合
      templateNameList: [],
      curSelectTemplate: {
        id: -1,
        name: '未知'
      },
      // 弹出层是否可见
      dialogFormVisible: false,
      // 选择跳转类型的弹出层
      answerTypeDialogVisible: false,
      currentRow: null,
      // 跳转类型
      answerTypes: [],
      // edgeLabel: [],
      selectedEdge: null,
      // 该source节点还未选择的跳转类型
      unSelectedAnswerTypes: [],
      // 节点属性
      // templateName: '',
      nodeForm: {
        id: -1,
        informType: '',
        name: '',
        category: '',
        scene: '',
        language: '',
        recorder: '',
        variables: '',
        content: '',
        type: '',
        speed: 1,
        // 高级配置
        beginTime: 0.5,
        waitTime: 3,
        noResponseTime: 5,
        jzdj: '',
        sbms: '',
        audioPath: ""
      },
      nodeRules: {
        informType: [
          { required: true, message: '模板类型不能为空'},
        ],
        name: [
          { required: true, message: '模板名称不能为空'},
        ],
        language: [
          { required: true, message: '话术语言不能为空'},
        ],
        recorder: [
          { required: true, message: '录音员不能为空'},
        ],
        audioPath: [
          { required: true, message: '音频不能为空'},
        ],
        type: [{ required: true, message: '请选择话术类型'}],
        content: [
          { required: true, message: '模板内容不能为空'},
        ],
      },
      newNodeInfo: {
        x: null,
        y: null,
        id: null,
        name: null,
        type: null,
      },
      edgeForm: {
        source: null,
        target: null,
        answerType: [],
      },
      edgeRules: {
        answerType: [
          // 验证规则
          { required: true, message: '跳转类型不能为空', trigger: 'blur' },
        ],
      },
      // audio相关设置
      audioUrl: '',
      audio: {
        playing: false,
        speed: 1,
      },
      speedValue50: 50,
      audioButton: '试听',
      // 参数设置
      variablesArr: [],
      // params: generateParams(),
      variables: this.getVariables(),
      // 高级配置
      highConfig: {
        beginTime: 10,
        waitTime: 60,
        noResponseTime: 50,
        // jzdj: '',
        // sbms: ''
      },
      filterMethod(query, item) {
        // return item.pinyin.indexOf(query) > -1
        return item.label.indexOf(query) > -1
      },
      categoryList: [],
      sceneList: [],
      jzdjList: [],
      sbmsList: [],
      sceneAllList: [
        { category: '金融', value: '借贷' },
        { category: '金融', value: '理财' },
        { category: '电商', value: '直播' },
        { category: '电商', value: '短视频' },
      ],
      recorderList: [],
      informType: ['AI话术模板', '语音通知'],
      // 意向中心设置
      // 是否显示话术模板列表
      showNameList: true,
      // 是否显示话术类型列表
      showMenuBar: true,
      // 是否显示意向配置
      showIntentionCenter: false,
      // 意向类型：0单意向，1多意向
      intentionType: "0",
      // 意向判断规则
      intentionJudgeConditionList: [],
      // 意向优先级最大值
      intentionMaxSort: 1,
      // 是否显示意向设置弹出框
      intentionDialogFormVisible: false,
      intentionDialogTitle: '添加意向',
      // 意向列表数据
      intentionData: [],
      // 意向表单数据
      intentionForm: {
        category: 'A',
        name: '',
        remark: '',
        allCondition:[],
        anyCondition:[],
        sort: 0
      },
    }
  },
  mounted() {
    this.getTemplateType()
    this.getTemplateNameList()
    this.getAnswerType()
    this.getIntentionJudgeConditionList()
    this.getRecorderList()
    this.getjzdjList()
    this.getsbmsList()
    this.getCategory()
    this.initGraph()
  },
  methods: {
    // 获取有多少结点类型
    getTemplateType() {
      const requestBody = {
        type: 'templateType',
        value: '',
        category: '',
        pageNum: 1,
        pageSize: 100,
      }
      getParamData(requestBody).then(response => {
        this.moduleList = []
        const respData = response.data.content
        for (let i = 0; i < respData.length; i++) {
          if (respData[i].name !== '开场白') {
            const elem = {
              id: respData[i].id,
              name: respData[i].name,
              type: 'logic',
            }
            this.moduleList.push(elem)
          }
        }
      })
    },
    // 获取跳转类型
    getAnswerType() {
      getSimpleList('answerType').then(response => {
        this.answerTypes = response.data
      })
    },
    // 获取意向判断规则列表
    getIntentionJudgeConditionList() {
      getSimpleList('intentionJudgeCondition').then(response => {
        this.intentionJudgeConditionList = response.data
      })
    },
    // 获取话术模板列表
    getTemplateNameList() {
      getTemplateNameList().then(response => {
        this.templateNameList = response.data
      })
    },
    // 话术模板名称被点击
    handleRowClick(val) {
      this.$refs.templateNameList.setCurrentRow(val)
      this.curSelectTemplate.id = this.$refs.templateNameList.store.states.currentRow._rawValue.id
      this.curSelectTemplate.name = this.$refs.templateNameList.store.states.currentRow._rawValue.name
      this.getTemplateFlowDiagram(val.id)
    },
    getTemplateFlowDiagram(id) {
      if (id !== -1) {
        getTemplateFlowDiagram(id).then(response => {
          this.getTemplateType()
          // 重新渲染话术节点
          this.graph.model.clear()
          for (let i = 0; i < response.data.nodes.length; i++) {
            response.data.nodes[i].id = response.data.nodes[i].id + ''
          }
          const respNode = response.data.nodes
          const respEdge = response.data.edges
          let model = {
            nodes: [],
            edges: []
          }
          model.nodes = respNode
          model.edges = respEdge
          const dagreLayout = new DagreLayout({
            type: 'dagre',
            rankdir: 'TB',
            align: 'DL',
            ranksep: 40,
            nodesep: 40,
            controlPoints: true,
          })
          dagreLayout.layout(model)

          // 添加节点
          const nodes = model.nodes
          for (let i = 0; i < nodes.length; i++) {
            if (nodes[i].type === '开场白') {
              this.addHandleNode(
                nodes[i].x,
                nodes[i].y,
                nodes[i].id,
                nodes[i].type,
                'initial'
              )
            } else {
              this.addHandleNode(
                nodes[i].x,
                nodes[i].y,
                nodes[i].id,
                nodes[i].type,
                'logic'
              )
            }
          }
          // 添加边
          const edges = model.edges
          for (let i = 0; i < edges.length; i++) {
            this.addHandelEdge(edges[i].source, edges[i].target, edges[i].label)
          }
          // 内容居中
          this.graph.centerContent()
        })
      } else {
        this.moduleList = [
          {
            id: 1,
            name: '开场白',
            type: 'initial',
          },
        ]
        this.graph.model.clear()
      }
    },
    // 初始化流程图画布
    initGraph() {
      let container = document.getElementById('container')
      this.graph = new Graph({
        container: container, // 画布容器
        width: container.offsetWidth, // 画布宽
        height: container.offsetHeight, // 画布高
        background: false, // 背景（透明）
        snapline: true, // 对齐线
        // 配置连线规则
        connecting: {
          snap: true, // 自动吸附
          allowBlank: false, //是否允许连接到画布空白位置的点
          allowMulti: false, //是否允许在相同的起始节点和终止之间创建多条边
          allowLoop: false, //是否允许创建循环连线，即边的起始节点和终止节点为同一节点
          highlight: true, //拖动边时，是否高亮显示所有可用的节点
          validateEdge({ edge, type, previous }) {
            // 连线时设置折线
            edge.setRouter({
              name: 'er',
            })
            // 设置连线样式
            edge.setAttrs({
              line: {
                stroke: '#275da3',
                strokeWidth: 4,
              },
            })
            return true
          },
        },
        panning: {
          enabled: true,
        },
        mousewheel: {
          enabled: true, // 支持滚动放大缩小
        },
        grid: {
          type: 'mesh',
          size: 20, // 网格大小 10px
          visible: true, // 渲染网格背景
          args: {
            color: '#eeeeee', // 网格线/点颜色
            thickness: 2, // 网格线宽度/网格点大小
          },
        },
      })
      this.nodeAddEvent()
    },
    // 生成代理画布、节点
    startDragToGraph(item, e) {
      console.log(item, 'item')
      console.log(e, 'e')
      const node = this.graph.createNode({
        shape: 'html',
        id: -1, // String，可选，节点的唯一标识
        width: 140, // Number，可选，节点大小的 width 值
        height: 50, // Number，可选，节点大小的 height 值
        html: `
            <div class="custom_node_initial">
              <div>
                <i>🌐</i>
              </div>
            </div>
            `,
        attrs: {
          // 这里给生成的节点的body加上透明的边框,一定要给边框宽度加上>0的值,否则节点将不能连线
          body: {
            stroke: 'transparent',
            strokeWidth: 10, // 边框的粗细
            magnet: true, // 节点是否可以连线
          }
        },
      })
      var _this = this
      const dnd = new Addon.Dnd({
        target: this.graph,
        // ☆拖拽结束时，验证节点是否可以放置到目标画布中。
        validateNode: (node) => {
          console.log('成功拖拽至目标画布')
          console.log(node.position(), 'validateNode')
          _this.resetNodeForm()
          _this.newNodeInfo.x = node.position().x
          _this.newNodeInfo.y = node.position().y
          _this.newNodeInfo.name = item.name
          _this.newNodeInfo.type = item.type
          _this.nodeForm.type = item.name
          _this.dialogFormVisible = true
        },
        getDragNode: (node) => {
          console.log(node, 'getDragNode')
          return node
        },
        getDropNode: (node) => {
          console.log(node, 'getDropNode')
          return node
        }
      })
      dnd.start(node, e)
    },
    addHandelEdge(source, target, label) {
      this.graph.addEdge({
        source: source,
        target: target,
        label: label,
        attrs: {
          line: {
            stroke: '#275da3',
            strokeWidth: 4,
          },
        },
        router: {
          name: 'er',
        },
      })
    },
    // 生成节点函数
    addHandleNode(x, y, id, name, type) {
      type === 'initial'
        ? this.graph.addNode(Tools.initInitialNode(x, y, id, name, type))
        : this.graph.addNode(Tools.initLogicNode(x, y, id, name, type))
    },
    // 节点node和边edge相关的事件
    nodeAddEvent() {
      // 节点绑定点击事件
      this.graph.on('node:click', ({ e, x, y, node, view }) => {
        // 判断是否有选中过节点
        if (this.curSelectNode) {
          // 移除选中状态
          this.curSelectNode.removeTools()
          // 判断两次选中节点是否相同
          if (this.curSelectNode !== node) {
            node.addTools([
              {
                name: 'boundary',
                args: {
                  attrs: {
                    fill: '#16B8AA',
                    stroke: '#2F80EB',
                    strokeWidth: 1,
                    fillOpacity: 0.1,
                  },
                },
              },
              {
                name: 'button-remove',
                args: {
                  x: '100%',
                  y: 0,
                  offset: {
                    x: 0,
                    y: 0,
                  },
                  onClick({ view }) {
                    const node = view.cell
                    console.log(node, 'node')
                    if (node.store.data.type === 'initial') {
                      // 显示确认框
                      const confirmed = confirm(
                        '删除开场白节点，整个话术模板将被删除，是否删除？'
                      )
                      // 如果用户点击了 "确认"，那么就调用原有的 "onClick" 方法
                      if (confirmed) {
                        this.graph.removeNode(node)
                        this.graph.model.clear()
                      }
                    } else {
                      const confirmed = confirm(
                        '是否删除？'
                      )
                      if (confirmed) {
                        const edges = this.graph.getConnectedEdges(node, {
                          incoming: true,
                          outgoing: true,
                        })
                        this.graph.removeCells(edges)
                        this.graph.removeNode(node)
                      }
                    }
                  },
                },
              },
            ])
            this.curSelectNode = node
          } else {
            this.curSelectNode = null
          }
        } else {
          this.curSelectNode = node
          node.addTools([
            {
              name: 'boundary',
              args: {
                attrs: {
                  fill: '#16B8AA',
                  stroke: '#2F80EB',
                  strokeWidth: 1,
                  fillOpacity: 0.1,
                },
              },
            },
            {
              name: 'button-remove',
              args: {
                x: '100%',
                y: 0,
                offset: {
                  x: 0,
                  y: 0,
                },
                onClick({ view }) {
                  const node = view.cell
                  console.log(node, 'node')
                  if (node.store.data.type === 'initial') {
                    // 显示确认框
                    const confirmed = confirm(
                      '删除开场白节点，整个话术模板将被删除，是否删除？'
                    )
                    // 如果用户点击了 "确认"，那么就调用原有的 "onClick" 方法
                    if (confirmed) {
                      this.graph.removeNode(node)
                      this.graph.model.clear()
                    }
                  } else {
                    const confirmed = confirm(
                      '是否删除？'
                    )
                    if (confirmed) {
                      const edges = this.graph.getConnectedEdges(node, {
                        incoming: true,
                        outgoing: true,
                      })
                      this.graph.removeCells(edges)
                      this.graph.removeNode(node)
                    }
                  }
                },
              },
            },
          ])
        }
      })
      // 连线绑定悬浮事件
      this.graph.on('cell:mouseenter', ({ cell }) => {
        if (cell.shape == 'edge') {
          cell.addTools([
            {
              name: 'button-remove',
              args: {
                x: '100%',
                y: 0,
                offset: {
                  x: 0,
                  y: 0,
                },
              },
            },
          ])
          cell.setAttrs({
            line: {
              stroke: '#409EFF',
            },
          })
          cell.zIndex = 99
        }
      })
      this.graph.on('cell:mouseleave', ({ cell }) => {
        if (cell.shape === 'edge') {
          cell.removeTools()
          cell.setAttrs({
            line: {
              stroke: '#275da3',
            },
          })
          cell.zIndex = 1
        }
      })
      this.graph.on('node:dblclick', ({ e, x, y, node, view }) => {
        console.log(node.position(), 'node-position')
        this.getTemplateById(node.id)
      })
      this.graph.on('edge:connected', ({ isNew, edge }) => {
        if (isNew) {
          this.edgeInfoReset(edge)
          this.answerTypeDialogVisible = true
        }
      })
      this.graph.on('edge:dblclick', ({ e, x, y, edge, view }) => {
        // 双击edge，弹出跳转类型的选择
        this.edgeInfoReset(edge)
        this.edgeForm.answerType = edge.store.data.labels[0].attrs.label.text.split(
          ','
        )
        this.answerTypeDialogVisible = true
      })
      this.graph.on('node:removed', ({ node, index, options }) => {
        if (options.clear === undefined || options.ui) {
          console.log('节点被用户点击删除了', node)
          console.log(node.store.data.type, 'type')
          // 发起请求，删除后端中的数据
          if (node.store.data.type === 'initial') {
            // 删除全部
            deleteTemplateAll(node.store.data.id).then(response => {
              if (response.code === 20000) {
                this.$message.success('删除成功!')
                this.getTemplateNameList()
              }
            })
          } else {
            deleteTemplateNode(node.id).then(response => {
              console.log(response, 'response')
            })
          }
        }
      })
      this.graph.on('edge:removed', ({ edge, index, options }) => {
        // console.log(options)
        if (options.clear !== true) {
          if (!(options.ui === true && options.toolId === undefined)) {
            console.log('边被用户点击删除了', edge)
            // 发起请求，删除后端中的flow
            const edgeDeleteForm = {
              source: edge.store.data.source.cell,
              target: edge.store.data.target.cell,
            }
            deleteTemplateEdge(edgeDeleteForm).then(response => {
              // 删除边成功
              // console.log(response, 'response')
            })
          }
        }
      })
    },
    // 创建新的话术模板
    createNewTemplate() {
      this.moduleList = [
        {
          id: 1,
          name: '开场白',
          type: 'initial',
        },
      ]
      const newRow = {
        id: -1,
        name: '未命名话术模板',
      }
      this.templateNameList.push(newRow)
      // 把当前新建的节点设置为选中，即高亮状态
      this.$refs.templateNameList.setCurrentRow(newRow)
      // 清空画布
      this.graph.model.clear()
    },
    edgeInfoReset(edge) {
      this.$nextTick(() => {
        if (this.$refs.edgeFormRef !== undefined) {
          this.$refs.edgeFormRef.clearValidate()
        }
      })
      this.newEdge = null
      this.edgeForm.answerType = []

      this.selectedEdge = edge
      this.unSelectedAnswerTypes = Array.from(this.answerTypes)
      this.graph.getEdges().forEach(edge1 => {
        if (
          edge1 !== edge &&
          edge1.store.data.source.cell == edge.store.data.source.cell &&
          edge1.store.data.labels
        ) {
          const label = edge1.store.data.labels[0].attrs.label.text
          const labels = label.split(',')
          for (let i = 0; i < labels.length; i++) {
            let index = this.unSelectedAnswerTypes.indexOf(labels[i])
            if (index !== -1) {
              this.unSelectedAnswerTypes.splice(index, 1)
            }
          }
        }
      })
    },
    onEdgeLabelSubmit() {
      this.$nextTick(() => {
        this.$refs.edgeFormRef.validate(valid => {
          if (valid) {
            console.log('点击确认')
            this.selectedEdge.setLabels([])
            this.selectedEdge.appendLabel(this.edgeForm.answerType.toString())
            // 对边进行数据库的持久化操作
            this.edgeForm.source = this.selectedEdge.store.data.source.cell
            this.edgeForm.target = this.selectedEdge.store.data.target.cell

            addTemplateEdge(this.edgeForm).then(response => {
              this.answerTypeDialogVisible = false
            })
          }
        })
      })
    },
    onEdgeLabelCancel() {
      console.log('点击取消')
      if (!this.selectedEdge.store.data.labels) {
        this.graph.removeEdge(this.selectedEdge)
      }
      this.answerTypeDialogVisible = false
    },
    // 拖动后松开鼠标触发事件
    handleDragEnd(e, item) {
      // 先发起弹出页面，创建后话术结点，发送给后端，保存数据，然后获取到id作为node的id
      this.resetNodeForm()
      this.newNodeInfo.x = e.pageX - 240
      this.newNodeInfo.y = e.pageY - 40
      // this.newNodeInfo.x = e.clientX
      // this.newNodeInfo.y = e.clientY
      this.newNodeInfo.name = item.name
      this.newNodeInfo.type = item.type
      this.nodeForm.type = item.name
      this.dialogFormVisible = true
    },
    onNodeSubmit() {
      // console.log('点击了确认')
      this.nodeForm.variables = this.variablesArr.toString()
      this.$refs.nodeForm.validate(valid => {
        if (valid) {
          if (this.newNodeInfo.name !== '开场白') {
            this.nodeForm.name = this.$refs.templateNameList.store.states.currentRow._rawValue.name
          }
          this.nodeForm.speed = this.audio.speed
          this.nodeForm.beginTime = this.highConfig.beginTime / 20
          this.nodeForm.waitTime = this.highConfig.waitTime / 20
          this.nodeForm.noResponseTime = this.highConfig.noResponseTime / 10
          updateTemplateInFlowDiagram(this.nodeForm).then(response => {
            const templateId = response.data
            if (templateId !== -1) {
              if (this.newNodeInfo.name === '开场白') {
                console.log(
                  this.$refs.templateNameList,
                  'this.$refs.templateNameList'
                )
                const currentRow = this.$refs.templateNameList.store.states
                  .currentRow._rawValue

                this.templateNameList.splice(
                  this.templateNameList.indexOf(currentRow),
                  1
                )
                const newRow = {
                  id: templateId,
                  name: this.nodeForm.name,
                }
                this.templateNameList.push(newRow)
                // 把当前新建的节点设置为选中，即高亮状态
                this.$refs.templateNameList.setCurrentRow(newRow)
                this.getTemplateType()
              }
              this.addHandleNode(
                this.newNodeInfo.x,
                this.newNodeInfo.y,
                templateId,
                this.newNodeInfo.name,
                this.newNodeInfo.type
              )
            }
            this.$message.success("保存成功!");
            this.dialogFormVisible = false
          })
          this.resetNodeForm()
        }
      })
    },
    onNodeCancel() {
      // console.log('点击的取消')
      // this.pausePlay()
      // this.resetForm()
      // 点击取消，关闭弹出框
      this.dialogFormVisible = false
      this.pausePlay()
      // this.resetForm()
      this.resetNodeForm()
    },
    resetNodeForm() {
      this.$nextTick(() => {
        if (this.$refs.nodeForm !== undefined) {
          this.$refs.nodeForm.clearValidate()
        }
      })
      this.nodeForm = {
        id: -1,
        informType: '',
        name: '',
        category: '',
        scene: '',
        language: '全合成',
        recorder: '',
        variables: '',
        content: '',
        type: '',
        jzdj: '正常',
        sbms: '通用模式',
        audioPath: ""
      }
      this.variablesArr = []
      this.highConfig = {
        beginTime: 10,
        waitTime: 60,
        noResponseTime: 50,
      }
    },
    getCategory() {
      getCategory().then(response => {
        this.categoryList = response.data
      })
    },
    getVariables() {
      const params = []
      getSimpleList('variable').then(response => {
        var valNames = response.data
        valNames.forEach((valName, index) => {
          params.push({
            label: valName,
            key: valNames[index],
          })
        })
      })
      return params
    },
    getRecorderList() {
      getRecorderList().then(response => {
        this.recorderList = response.data
      })
    },
    getjzdjList() {
      getSimpleList('jzdj').then(response => {
        this.jzdjList = response.data
      })
    },
    getsbmsList() {
      getSimpleList('sbms').then(response => {
        this.sbmsList = response.data
      })
    },
    // 双击节点node时，获取template的详细数据
    getTemplateById(id) {
      this.resetNodeForm()
      getTemplateById(id).then(response => {
        const templateVO = response.data
        this.nodeForm.id = templateVO.id
        this.nodeForm.type = templateVO.type
        this.nodeForm.informType = templateVO.informType
        this.nodeForm.language = templateVO.language
        this.nodeForm.recorder = templateVO.recorder
        this.nodeForm.content = templateVO.content
        this.nodeForm.audioPath = templateVO.audioPath
        this.variablesArr = templateVO.variables.split(',')
        // 设置名称,分类,应用场景
        this.nodeForm.name = templateVO.name
        this.nodeForm.category = templateVO.category
        this.nodeForm.scene = templateVO.scene
        // 设置高级配置
        this.audio.speed = templateVO.speed
        this.highConfig.beginTime = templateVO.beginTime * 20
        this.highConfig.waitTime = templateVO.waitTime * 20
        this.highConfig.noResponseTime = templateVO.noResponseTime * 10
        this.speedValue50 = templateVO.speed * 50
        this.nodeForm.jzdj = templateVO.jzdj
        this.nodeForm.sbms = templateVO.sbms
        this.dialogFormVisible = true
      })
    },
    // 分类和应用场景联动选择
    getScene(category) {
      getScene(category).then(response => {
        this.sceneAllList = response.data
        this.nodeForm.scene = ''
        this.sceneList = []
        for (var scene of this.sceneAllList) {
          if (scene.category === category) {
            this.sceneList.push(scene)
          }
        }
      })
    },
    // 参数选择变化函数
    variableChange(value, direction, arr) {
      if (direction === 'right') {
        for (let i = 0; i < arr.length; i++) {
          this.nodeForm.content += '{{' + arr[i] + '}}'
        }
      }
      if (direction === 'left') {
        for (let i = 0; i < arr.length; i++) {
          this.nodeForm.content = this.nodeForm.content.replaceAll(
            '{{' + arr[i] + '}}',
            ''
          )
        }
      }
    },
    // 试听相关方法
    startPlayOrPause() {
      this.audio.playing ? this.pausePlay() : this.startPlay()
    },
    // 开始播放
    startPlay() {
      if (this.nodeForm.language === '') {
        this.$message.error("请先选择话术语音!");
        return
      }
      let audioPath = "";
      if (this.nodeForm.language === '全合成') {
        const recorder = this.nodeForm.recorder;
        this.recorderList.forEach(item => {
          if (item.name === recorder) {
            audioPath = item.audioPath
          }
        })
        if (audioPath === '' || audioPath === null) {
          this.$message.error("录音员未选择或该录音员未配置试听音频!");
          return
        }
      }
      if (this.nodeForm.language === '全录音') {
        if (this.nodeForm.audioPath === '') {
          this.$message.error("请先上传音频!");
          return
        } else {
          audioPath = this.nodeForm.audioPath;
        }
      }
      Promise.all([this.getAudioByPath(audioPath)]).then(res => {
        if (res == -1) {
          return
        } else {
          this.audio.playing = true
          this.audioButton = '暂停'
          this.$refs.audio.currentTime = 0
          this.$refs.audio.playbackRate = this.audio.speed
          this.$refs.audio.play()
        }
      })
    },
    // 暂停
    pausePlay() {
      this.audio.playing = false
      this.audioButton = '试听'
      // this.speedValue50 = 50
      this.$refs.audio.pause()
    },
    formatTooltip(val) {
      if (val == null) {
        val = 50
      }
      if (val <= 4) {
        val = 4
      }
      // console.log(val, 'val')
      const speed = val / 50
      this.audio.speed = speed
      if (this.$refs.audio !== undefined) {
        this.$refs.audio.playbackRate = speed
      }
      return speed
    },
    formatBeginTime(val) {
      return val / 20
    },
    formatWaitTime(val) {
      return val / 20
    },
    formatNoResponseTime(val) {
      return val / 10
    },
    handleChangeSpeed(speed) {
      this.speedValue50 = speed * 50
      this.$refs.audio.playbackRate = speed
    },
    // 获取音频
    async getAudioByPath(audioPath) {
      try {
        const response = await axios({
          url: audioPath,
          method: "GET",
          responseType: "blob"
        });
        if (response.data.type === "application/json") {
          // console.log('获取音频失败!')
          this.$message.error("获取音频失败!");
          return -1;
        }
        const audioBlob = new Blob([response.data], { type: "audio/mpeg" });
        this.audioUrl = URL.createObjectURL(audioBlob);
      } catch (error) {
        // console.log('获取音频失败!')
        this.$message.error("获取音频失败!");
        return -1;
      }
    },
    uploadAudio(options){
      const formData = new FormData;
      formData.append('file',options.file);
      request.post('/audio/uploadAudio', formData, {
        headers: {
          'Content-Type': 'multipart/form-data',
        },
      }).then(res => {
        options.onSuccess(res, options.file)
      }).catch(error => {
        this.$message.error("上传音频失败!");
      })
    },
    // 上传音频
    uploadAudioSuccess(resp) {
      this.nodeForm.audioPath = resp.data;
      this.$message.success("上传成功!");
      this.$refs.nodeForm.validateField('audioPath')
    },
    // 拖动节点到画布中鼠标样式变为可拖动状态
    dragoverDiv(ev) {
      ev.preventDefault()
    },
    // 意向设置相关方法
    enterIntentionCenter() {
      this.showNameList = false
      this.showMenuBar = false
      this.intentionType = '0'
      this.showIntentionCenter = true
      this.getTemplateFlowDiagram(this.curSelectTemplate.id)
      this.getIntentionData()
    },
    exitIntentionCenter() {
      this.showIntentionCenter = false
      this.showNameList = true
      this.showMenuBar = true
      this.graph.centerContent()
    },
    intentionDialogHandleClose() {
      this.intentionDialogFormVisible = false
      this.resetIntentionForm()
    },
    intentionHandle() {
      if (this.intentionDialogTitle == '添加意向') {
        this.addIntentionHandle()
      } else {
        this.updateIntentionHandle()
      }
    },
    // 新增意向
    addIntention() {
      this.intentionDialogTitle = '添加意向'
      this.intentionDialogFormVisible = true
      if (this.intentionType === '0') {
        this.intentionForm.sort = this.intentionMaxSort
      } else {
        this.intentionForm.sort = 1
      }
    },
    // 添加意向执行
    addIntentionHandle() {
      if (this.intentionForm.name === '') {
        this.$message.error("意向名称不能为空！")
        return
      }
      if (this.intentionForm.allCondition.length === 0 && this.intentionForm.anyCondition.length === 0) {
        this.$message.error("判断规则不能为空！")
        return
      }
      this.intentionForm.intentionType = this.intentionType
      this.intentionForm.templateId = this.curSelectTemplate.id
      addIntention(this.intentionForm).then(response => {
        console.log('addIntentionResp', response)
        this.$message.success("添加成功!");
        this.intentionDialogFormVisible = false
        this.getIntentionData()
        this.resetIntentionForm()
      })
    },
    // 修改意向
    updateIntention(intention) {
      this.intentionDialogTitle = '修改意向'

      this.intentionForm.id = intention.id
      this.intentionForm.templateId = intention.templateId
      this.intentionForm.sort = intention.sort
      this.intentionForm.category = intention.category
      this.intentionForm.name = intention.name
      this.intentionForm.remark = intention.remark
      this.intentionForm.allCondition = intention.allCondition
      this.intentionForm.anyCondition = intention.anyCondition
      this.intentionForm.intentionType = this.intentionType

      this.intentionDialogFormVisible = true
    },
    // 修改意向执行
    updateIntentionHandle() {
      console.log('intentionForm', this.intentionForm)
      updateIntention(this.intentionForm).then(response => {
        console.log('updateIntentionResp', response)
        this.$message.success("修改成功!");
        this.intentionDialogFormVisible = false
        this.getIntentionData()
        this.resetIntentionForm()
      })
    },
    // 删除意向
    deleteIntention(intention) {
      this.$confirm("是否删除该意向?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        console.log('intention', intention)
        deleteIntentionById(intention.id).then(response => {
          this.$message.success("删除成功!");
          this.getIntentionData()
        })
        }).catch(() => {
        // 用户点击了取消按钮，不执行任何操作
        this.$message.info("取消成功");
      });
    },
    resetIntentionForm() {
      this.intentionForm = {
        category: 'A',
        name: '',
        remark: '',
        allCondition:[],
        anyCondition:[],
        sort: 1
      }
    },
    // 意向类型发生变化，重新获取数据
    intentionTypeChange() {
      this.getIntentionData()
    },
    // 获取意向数据列表
    getIntentionData() {
      let requestBody = {
        templateId: this.curSelectTemplate.id,
        intentionType: this.intentionType
      }
      getIntentionData(requestBody).then(response => {
        console.log('getIntentionDataResp', response)
        this.intentionData = response.data
        this.intentionMaxSort = 1
        for (let i = 0; i < this.intentionData.length; i++) {
          let sortVal = this.intentionData[i].sort + 1
          this.intentionMaxSort = this.intentionMaxSort > sortVal ? this.intentionMaxSort : sortVal
        }
      })
    },
  },
}
</script>
<style lang="less" scoped>
.home {
  width: 100%;
  height: 100%;
  display: flex;
  padding: 20px;
  box-sizing: border-box;
  background: #eaeaea;
  > div {
    background: #ffffff;
    border-radius: 5px;
  }
  //@ztColor: #da222a;
  //.name-list {
  //  /* 用来设置当前页面element全局table 选中某行时的背景色*/
  //  .current-row {
  //    .el-table__cell {
  //      background-color: red !important;
  //    }
  //  }
  //}
  .name-list {
    width: 250px;
    margin-right: 20px;
  }
  // 话术类型部分
  .menu-bar {
    width: 200px;
    height: 100%;
    margin-right: 20px;
    display: flex;
    flex-direction: column;
    h2 {
      width: 100%;
      font-size: 20px;
      padding: 10px;
      box-sizing: border-box;
      margin: 0;
    }
    .menu-list {
      height: 0;
      flex: 1;
      overflow: auto;
      padding: 0 10px;
      box-sizing: border-box;
      > div {
        border: 2px dashed #eaeaea;
        margin-bottom: 10px;
        border-radius: 5px;
        padding: 0 10px;
        box-sizing: border-box;
        cursor: pointer;
      }
    }
  }
  // 意向中心
  .intention-center {
    width: 470px;
    margin-right: 20px;
    .top {
      margin-bottom: 10px;
    }
    .middle {
      margin-bottom: 10px;
    }
  }
  // 画布部分
  .canvas-card {
    width: 0;
    flex: 1;
    height: 100%;
    padding: 20px;
    box-sizing: border-box;
    > div {
      width: 100%;
      height: 100%;
      border: 2px dashed #eaeaea;
    }
  }
}
</style>
<style lang="less">
// 其中节点样式加到没有scoped包裹的style标签中，否则样式不生效
// 初始节点样式
.custom_node_initial {
  width: 100%;
  height: 100%;
  display: flex;
  border-radius: 3px;
  background: rgba(22, 184, 169, 0.6);
  flex-direction: column;
  overflow: hidden;
  > div {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 5px;
    box-sizing: border-box;
    border: 5px solid rgba(47, 128, 235, 0.6);
    i {
      line-height: 22px;
      font-size: 18px;
      color: #ffffff;
      display: flex;
      align-items: center;
      margin-right: 5px;
      justify-content: center;
      font-style: normal;
    }
    p {
      color: #ffffff;
      font-size: 16px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
}
// 逻辑节点样式
.custom_node_logic {
  width: 100%;
  height: 100%;
  display: flex;
  background: rgba(47, 128, 235, 0.5);
  flex-direction: column;
  overflow: hidden;
  border-radius: 5px;
  > div {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 5px;
    box-sizing: border-box;
    border: 5px solid rgba(22, 184, 169, 0.5);
    border-radius: 5px;
    line-height: 22px;
    i {
      line-height: 22px;
      font-size: 18px;
      color: #b5cde9;
      margin-right: 5px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-style: normal;
    }
    p {
      color: #ffffff;
      font-size: 14px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
}
</style>
